<!--
 * @Author: zhangmengqiong
 * @Date: 2021-04-26 10:36:18
 * @LastEditors: zhangmengqiong
 * @LastEditTime: 2021-04-26 12:42:42
-->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>图片压缩</title>
  </head>
  <body>
    <input type="file" id="upload" />
  </body>
  <script>
    // 可接受文件类型
    const ACCEPT = ['image/jpg', 'image/png', 'image/jpeg'];
    const MaxSize = 1024 * 1024;
    const upload = document.getElementById('upload');
    // 将图片转化成base64
    function converImageToBase64(file, callback) {
      // 实例化fileReader对象
      let reader = new FileReader();
      // 文件加载完成之后
      reader.addEventListener('load', function (e) {
        const base64Image = e.target.result;
        callback && callback(base64Image);
        // 完成之后，让内存去回收 reader
        reader = null;
      });
      reader.readAsDataURL(file);
    }
    // 上传函数方法
    function uploadToServer(compressImage) {
      // 将压缩后的图片上传到服务器
      console.log(compressImage, 'compressImage');
    }
    // 图片压缩函数 思路：1,图片尺寸压缩，获取图片宽高 2，图片输出分辨率
    function compressImage(base64Image, callback) {
      let maxW = 1024;
      let maxH = 1024;
      // 渲染图片
      const image = new Image();
      // 对图片宽高进行压缩
      image.addEventListener('load', function (e) {
        let ratio; // 图片压缩比
        let needCompress = false; // 是否需要压缩
        // 获取图片的原始宽高  image.naturalWidth, image.naturalHeight
        // 先判断图片宽度是否要压缩
        if (maxW < image.naturalWidth) {
          needCompress = true;
          // 计算压缩比
          ratio = image.naturalWidth / maxW;
          console.log(ratio, 'ratio'); // 1.25
          // 图片高度也是要同比压缩,经过压缩之后的图片宽高比例不变
          maxH = image.naturalHeight / ratio;
          // 经过压缩之后的图片尺寸为 1024 * 724
          console.log(image.naturalWidth, image.naturalHeight, maxH, 'maxH'); // 1280 905 704
        }
        // 判断图片高度是否要压缩
        if (maxH < image.naturalHeight) {
          needCompress = true;
          ratio = image.naturalHeight / maxH;
          maxW = image.naturalWidth / ratio;
        }
        // 不需要压缩，获取图片的实际尺寸
        if (!needCompress) {
          maxW = image.naturalWidth;
          maxH = image.naturalHeight;
        }
        // 最后使用canvas 重新绘制压缩图片

        const canvas = document.createElement('canvas');
        canvas.setAttribute('id', '_compress_');
        canvas.width = maxW;
        canvas.height = maxH;
        // 压缩效果,实际过程中，隐藏压缩过程，设置为hidden
        canvas.style.visibility = 'hidden';
        document.body.appendChild(canvas);

        // 进行绘图
        const ctx = canvas.getContext('2d');
        ctx.clearRect(0, 0, maxW, maxH);
        // 绘制图片
        ctx.drawImage(image, 0, 0, maxW, maxH);
        // 将图片转换为base64,第一个是参数是图片类型，第二个，压缩参数 0-1,一般设置0.8，0.9
        const compressImage = canvas.toDataURL('image/jpg', 0.1);
        // 将压缩后的图片保存
        callback && callback(compressImage);
        canvas.remove();
        // // 展示对比效果
        // const imageCompressNode = new Image();
        // imageCompressNode.src = compressImage;
        // console.log(imageCompressNode.size);
        // document.body.appendChild(imageCompressNode);
      });
      // image.src = base64Image;
      // document.body.appendChild(image);
    }
    upload.addEventListener('change', function (e) {
      // 数组解构写法
      // 等价于 const file = e.target.files[0]
      const [file] = e.target.files;
      if (!file) {
        return;
      }
      const { type: fileType, size: fileSize } = file;
      // 判断文件类型是否包含在里面
      if (!ACCEPT.includes(fileType)) {
        console.log(`不支持${fileType}文件类型`);
        upload.value = '';
        return;
      }
      // 图片容量检查
      if (fileSize > MaxSize) {
        console.log(`文件超出${MaxSize}`);
        upload.value = '';
        return;
      }
      // 压缩图片
      /*
       * 1,将文件转成base64
         2,计算压缩比，通过最大高度，最大宽度进行计算
         3，使用canvas 重新绘制（压缩尺寸后的）
         4，进行分辨率压缩，使用canvas.toDataURL进行二次压缩
       * 5,将图片保存并上传到服务器(传入文件及回调函数)
       */
      converImageToBase64(file, base64Image =>
        compressImage(base64Image, uploadToServer)
      );
    });
  </script>
</html>
